var createServer = require("http").createServer;
var readFile = require("fs").readFile;
var sys = require("sys");
var url = require("url");
DEBUG = false;

var fu = exports;

var NOT_FOUND = "Not Found\n";

function notFound(req, res) {
    res.writeHead(404, {
        "Content-Type": "text/plain"
        , 
        "Content-Length": NOT_FOUND.length
    });
    res.end(NOT_FOUND);
}

var getMap = {};

fu.get = function (path, handler) {
    getMap[path] = handler;
};
var server = createServer(function (req, res) {
    if (req.method === "GET" || req.method === "HEAD") {
        var handler = getMap[url.parse(req.url).pathname] || notFound;

        res.simpleText = function (code, body) {
            res.writeHead(code, {
                "Content-Type": "text/plain"
                , 
                "Content-Length": body.length
            });
            res.end(body);
        };

        res.simpleJSON = function (code, obj) {
            var body = new Buffer(JSON.stringify(obj));
            res.writeHead(code, {
                "Content-Type": "text/json"
                , 
                "Content-Length": body.length
            });
            res.end(body);
        };

        handler(req, res);
    }
});

fu.listen = function (port, host) {
    server.listen(port, host);
    sys.puts("Server at http://" + (host || "127.0.0.1") + ":" + port.toString() + "/");
};

fu.close = function () {
    server.close();
};

function extname (path) {
    var index = path.lastIndexOf(".");
    return index < 0 ? "" : path.substring(index);
}

fu.staticHandler = function (filename) {
    var body, headers;
    var content_type = fu.mime.lookupExtension(extname(filename));

    function loadResponseData(callback) {
        if (body && headers && !DEBUG) {
            callback();
            return;
        }

        sys.puts("loading " + filename + "...");
        readFile(filename, function (err, data) {
            if (err) {
                sys.puts("Error loading " + filename);
            } else {
                body = data;
                headers = {
                    "Content-Type": content_type
                    , 
                    "Content-Length": body.length
                };
                if (!DEBUG) headers["Cache-Control"] = "public";
                sys.puts("static file " + filename + " loaded");
                callback();
            }
        });
    }

    return function (req, res) {
        loadResponseData(function () {
            res.writeHead(200, headers);
            res.end(req.method === "HEAD" ? "" : body);
        });
    }
};

// stolen from jack- thanks
fu.mime = {
    // returns MIME type for extension, or fallback, or octet-steam
    lookupExtension : function(ext, fallback) {
        return fu.mime.TYPES[ext.toLowerCase()] || fallback || 'application/octet-stream';
    },

    // List of most common mime-types, stolen from Rack.
    TYPES : {
        ".3gp"   : "video/3gpp"
        , 
        ".a"     : "application/octet-stream"
        , 
        ".ai"    : "application/postscript"
        , 
        ".aif"   : "audio/x-aiff"
        , 
        ".aiff"  : "audio/x-aiff"
        , 
        ".asc"   : "application/pgp-signature"
        , 
        ".asf"   : "video/x-ms-asf"
        , 
        ".asm"   : "text/x-asm"
        , 
        ".asx"   : "video/x-ms-asf"
        , 
        ".atom"  : "application/atom+xml"
        , 
        ".au"    : "audio/basic"
        , 
        ".avi"   : "video/x-msvideo"
        , 
        ".bat"   : "application/x-msdownload"
        , 
        ".bin"   : "application/octet-stream"
        , 
        ".bmp"   : "image/bmp"
        , 
        ".bz2"   : "application/x-bzip2"
        , 
        ".c"     : "text/x-c"
        , 
        ".cab"   : "application/vnd.ms-cab-compressed"
        , 
        ".cc"    : "text/x-c"
        , 
        ".chm"   : "application/vnd.ms-htmlhelp"
        , 
        ".class"   : "application/octet-stream"
        , 
        ".com"   : "application/x-msdownload"
        , 
        ".conf"  : "text/plain"
        , 
        ".cpp"   : "text/x-c"
        , 
        ".crt"   : "application/x-x509-ca-cert"
        , 
        ".css"   : "text/css"
        , 
        ".csv"   : "text/csv"
        , 
        ".cxx"   : "text/x-c"
        , 
        ".deb"   : "application/x-debian-package"
        , 
        ".der"   : "application/x-x509-ca-cert"
        , 
        ".diff"  : "text/x-diff"
        , 
        ".djv"   : "image/vnd.djvu"
        , 
        ".djvu"  : "image/vnd.djvu"
        , 
        ".dll"   : "application/x-msdownload"
        , 
        ".dmg"   : "application/octet-stream"
        , 
        ".doc"   : "application/msword"
        , 
        ".dot"   : "application/msword"
        , 
        ".dtd"   : "application/xml-dtd"
        , 
        ".dvi"   : "application/x-dvi"
        , 
        ".ear"   : "application/java-archive"
        , 
        ".eml"   : "message/rfc822"
        , 
        ".eps"   : "application/postscript"
        , 
        ".exe"   : "application/x-msdownload"
        , 
        ".f"     : "text/x-fortran"
        , 
        ".f77"   : "text/x-fortran"
        , 
        ".f90"   : "text/x-fortran"
        , 
        ".flv"   : "video/x-flv"
        , 
        ".for"   : "text/x-fortran"
        , 
        ".gem"   : "application/octet-stream"
        , 
        ".gemspec" : "text/x-script.ruby"
        , 
        ".gif"   : "image/gif"
        , 
        ".gz"    : "application/x-gzip"
        , 
        ".h"     : "text/x-c"
        , 
        ".hh"    : "text/x-c"
        , 
        ".htm"   : "text/html"
        , 
        ".html"  : "text/html"
        , 
        ".ico"   : "image/vnd.microsoft.icon"
        , 
        ".ics"   : "text/calendar"
        , 
        ".ifb"   : "text/calendar"
        , 
        ".iso"   : "application/octet-stream"
        , 
        ".jar"   : "application/java-archive"
        , 
        ".java"  : "text/x-java-source"
        , 
        ".jnlp"  : "application/x-java-jnlp-file"
        , 
        ".jpeg"  : "image/jpeg"
        , 
        ".jpg"   : "image/jpeg"
        , 
        ".js"    : "application/javascript"
        , 
        ".json"  : "application/json"
        , 
        ".log"   : "text/plain"
        , 
        ".m3u"   : "audio/x-mpegurl"
        , 
        ".m4v"   : "video/mp4"
        , 
        ".man"   : "text/troff"
        , 
        ".mathml"  : "application/mathml+xml"
        , 
        ".mbox"  : "application/mbox"
        , 
        ".mdoc"  : "text/troff"
        , 
        ".me"    : "text/troff"
        , 
        ".mid"   : "audio/midi"
        , 
        ".midi"  : "audio/midi"
        , 
        ".mime"  : "message/rfc822"
        , 
        ".mml"   : "application/mathml+xml"
        , 
        ".mng"   : "video/x-mng"
        , 
        ".mov"   : "video/quicktime"
        , 
        ".mp3"   : "audio/mpeg"
        , 
        ".mp4"   : "video/mp4"
        , 
        ".mp4v"  : "video/mp4"
        , 
        ".mpeg"  : "video/mpeg"
        , 
        ".mpg"   : "video/mpeg"
        , 
        ".ms"    : "text/troff"
        , 
        ".msi"   : "application/x-msdownload"
        , 
        ".odp"   : "application/vnd.oasis.opendocument.presentation"
        , 
        ".ods"   : "application/vnd.oasis.opendocument.spreadsheet"
        , 
        ".odt"   : "application/vnd.oasis.opendocument.text"
        , 
        ".ogg"   : "application/ogg"
        , 
        ".p"     : "text/x-pascal"
        , 
        ".pas"   : "text/x-pascal"
        , 
        ".pbm"   : "image/x-portable-bitmap"
        , 
        ".pdf"   : "application/pdf"
        , 
        ".pem"   : "application/x-x509-ca-cert"
        , 
        ".pgm"   : "image/x-portable-graymap"
        , 
        ".pgp"   : "application/pgp-encrypted"
        , 
        ".pkg"   : "application/octet-stream"
        , 
        ".pl"    : "text/x-script.perl"
        , 
        ".pm"    : "text/x-script.perl-module"
        , 
        ".png"   : "image/png"
        , 
        ".pnm"   : "image/x-portable-anymap"
        , 
        ".ppm"   : "image/x-portable-pixmap"
        , 
        ".pps"   : "application/vnd.ms-powerpoint"
        , 
        ".ppt"   : "application/vnd.ms-powerpoint"
        , 
        ".ps"    : "application/postscript"
        , 
        ".psd"   : "image/vnd.adobe.photoshop"
        , 
        ".py"    : "text/x-script.python"
        , 
        ".qt"    : "video/quicktime"
        , 
        ".ra"    : "audio/x-pn-realaudio"
        , 
        ".rake"  : "text/x-script.ruby"
        , 
        ".ram"   : "audio/x-pn-realaudio"
        , 
        ".rar"   : "application/x-rar-compressed"
        , 
        ".rb"    : "text/x-script.ruby"
        , 
        ".rdf"   : "application/rdf+xml"
        , 
        ".roff"  : "text/troff"
        , 
        ".rpm"   : "application/x-redhat-package-manager"
        , 
        ".rss"   : "application/rss+xml"
        , 
        ".rtf"   : "application/rtf"
        , 
        ".ru"    : "text/x-script.ruby"
        , 
        ".s"     : "text/x-asm"
        , 
        ".sgm"   : "text/sgml"
        , 
        ".sgml"  : "text/sgml"
        , 
        ".sh"    : "application/x-sh"
        , 
        ".sig"   : "application/pgp-signature"
        , 
        ".snd"   : "audio/basic"
        , 
        ".so"    : "application/octet-stream"
        , 
        ".svg"   : "image/svg+xml"
        , 
        ".svgz"  : "image/svg+xml"
        , 
        ".swf"   : "application/x-shockwave-flash"
        , 
        ".t"     : "text/troff"
        , 
        ".tar"   : "application/x-tar"
        , 
        ".tbz"   : "application/x-bzip-compressed-tar"
        , 
        ".tcl"   : "application/x-tcl"
        , 
        ".tex"   : "application/x-tex"
        , 
        ".texi"  : "application/x-texinfo"
        , 
        ".texinfo" : "application/x-texinfo"
        , 
        ".text"  : "text/plain"
        , 
        ".tif"   : "image/tiff"
        , 
        ".tiff"  : "image/tiff"
        , 
        ".torrent" : "application/x-bittorrent"
        , 
        ".tr"    : "text/troff"
        , 
        ".txt"   : "text/plain"
        , 
        ".vcf"   : "text/x-vcard"
        , 
        ".vcs"   : "text/x-vcalendar"
        , 
        ".vrml"  : "model/vrml"
        , 
        ".war"   : "application/java-archive"
        , 
        ".wav"   : "audio/x-wav"
        , 
        ".wma"   : "audio/x-ms-wma"
        , 
        ".wmv"   : "video/x-ms-wmv"
        , 
        ".wmx"   : "video/x-ms-wmx"
        , 
        ".wrl"   : "model/vrml"
        , 
        ".wsdl"  : "application/wsdl+xml"
        , 
        ".xbm"   : "image/x-xbitmap"
        , 
        ".xhtml"   : "application/xhtml+xml"
        , 
        ".xls"   : "application/vnd.ms-excel"
        , 
        ".xml"   : "application/xml"
        , 
        ".xpm"   : "image/x-xpixmap"
        , 
        ".xsl"   : "application/xml"
        , 
        ".xslt"  : "application/xslt+xml"
        , 
        ".yaml"  : "text/yaml"
        , 
        ".yml"   : "text/yaml"
        , 
        ".zip"   : "application/zip"
    }
};
